﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Visual_App
{
    /// <summary>
    /// Spezielle Visu für Approximation
    /// </summary>
    public partial class _frm_Approx : Form
    {
        private bool allow_close = false;
        private delegate void _del_REFR(IVisual.I_Network _N);

        private double[,] solution = new double[50, 2];
        private float[] networkInput = new float[1];

        public _frm_Approx()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Zeichnet ein Netz
        /// </summary>
        /// <param name="_N">Netzwerk zum zeichnen</param>
        public void REFR(IVisual.I_Network _N)
        {
            if (this.InvokeRequired)
                this.Invoke(new _del_REFR(this.REFR), _N);
            else
            {
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "start");
                // transformations faktor
                double yFactor = 1.7 / this._chart.RangeY.Length;
                double yMin = this._chart.RangeY.Min;
                double xFactor = 2.0 / this._chart.RangeX.Length;
                double xMin = this._chart.RangeX.Min;
                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "yFactor=" + yFactor + " yMin=" + yMin + " xFactor=" + xFactor + " xMin=" + xMin);
                // Netzausgabe einsetzten
                for (int j = 0; j < 50; j++)
                {
                    networkInput[0] = (float)((solution[j, 0] - xMin) * xFactor - 1.0);
                    IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "networkInput[0]=" + networkInput[0]);

                    double _tmp = (_N.Compute(networkInput)[0] + 0.85) / yFactor + yMin;
                    IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.DEBUG, "solution[" + j + ", 1]=" + solution[j, 1]);
                    solution[j, 1] = _tmp;
                }

                this._chart.UpdateDataSeries("solution", solution);

                IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "ende");
            }
        }

        /// <summary>
        /// Initialisiert die Ansicht, mithilfe der daten aus der cfg
        /// </summary>
        /// <param name="_data">daten aus der cfg</param>
        public void INIT(double[,] _data)
        {
            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "start");

            double minX = double.MaxValue;
            double maxX = double.MinValue;
            for(int i=0; i<_data.GetLength(0); i++)
            {
                // min Wert ermitteln
                if (_data[i, 0] < minX)
                    minX = _data[i, 0];
                // max Wert ermitteln
                if (_data[i, 0] > maxX)
                    maxX = _data[i, 0];
            }

            solution = new double[50, 2];
            networkInput = new float[1];

            this._chart.RangeX = new AForge.Range((float)minX, (float)maxX);
            this._chart.UpdateDataSeries("data", _data);
            this._chart.UpdateDataSeries("solution", null);

            // berechne X-Werte, welche in das Netz eingesetzt werden
            for (int j = 0; j < 50; j++)
            {
                solution[j, 0] = this._chart.RangeX.Min + (double)j * this._chart.RangeX.Length / 49;
            }

            IVisual._SC.cls_LOG.WRITE_LOG_LINE(IVisual._SC.cls_LOG.LOGLEVEL.METHOD_INVOKE, "ende");
        }

        private void _frm_Approx_Load(object sender, EventArgs e)
        {
            this._chart.AddDataSeries("data", Color.Red, AForge.Controls.Chart.SeriesType.Dots, 5);
            this._chart.AddDataSeries("solution", Color.Blue, AForge.Controls.Chart.SeriesType.ConnectedDots, 5);
        }

        /// <summary>
        /// Per Programm fenster schließen
        /// </summary>
        public void DO_CLOSE()
        {
            this.allow_close = true;
            this.Close();
        }

        private void _frm_Approx_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = !this.allow_close;
        }
    }
}
